package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.model.CartInfo;
import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.product.model.SkuInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("all")
public class CartServiceImpl implements CartService {

    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 将商品加入购物车
     * @param userId
     * @param skuId
     * @param skuNum
     */
    @Override
    public void addToCart(String userId, Long skuId, Integer skuNum) {
        //1.远程调用商品微服务获取商品信息,TODO:改为异步操作
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);

        //2.远程调用商品微服务获取商品价格
        BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);

        //3.构建用户购物车hash结构key
        String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        //3.1创建操作hash类型操作对象,绑定某个key
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        //4.将用户购物车商品加入redis.判断商品是否存在
        Boolean flag = hashOps.hasKey(skuId.toString());
        CartInfo cartInfo = null;
        if(flag){
            //4.1存在,购物车数量+1
            cartInfo = hashOps.get(skuId.toString());
            cartInfo.setSkuNum(cartInfo.getSkuNum()+skuNum);
        }else{
            //4.2不存在,往购物车中新增商品
            cartInfo = new CartInfo();
            BeanUtils.copyProperties(skuInfo, cartInfo);
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setCartPrice(skuPrice);
            cartInfo.setSkuPrice(skuPrice);
            cartInfo.setSkuNum(skuNum);
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
        }
        hashOps.put(skuId.toString(), cartInfo);
    }

    /**
     * 查询当前用户购物车列表(登录用户,临时用户)
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        //1.判断临时用户id是否有值,查询未登录购物车列表并且返回
        List<CartInfo> noLoginCartList = null;
        if(StringUtils.isNotBlank(userTempId)){
            String redisKey = RedisConst.USER_KEY_PREFIX + userTempId + RedisConst.USER_CART_KEY_SUFFIX;
            BoundHashOperations<String,String,CartInfo> noLoginHashOps = redisTemplate.boundHashOps(redisKey);
            noLoginCartList = noLoginHashOps.values();
        }
        //1.1如果用户未登录,直接返回未登录购物车列表
        if(StringUtils.isBlank(userId)){
            //1.2对购物车集合排序
            noLoginCartList = noLoginCartList.stream().sorted((o1, o2) -> {
                //比较相邻两个购物车对象中创建时间
                return DateUtil.truncatedCompareTo(o1.getCreateTime(), o2.getCreateTime(), Calendar.SECOND);
            }).collect(Collectors.toList());
            return noLoginCartList;
        }

        //2.用户真正登录
        //2.1判断登录的用户id是否有值,查询到已登录用户购物车列表返回
        String loginRedisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String,String,CartInfo> loginHashOps = redisTemplate.boundHashOps(loginRedisKey);

        //2.2判断未登录购物车数据列表和当前购物车数据列表进行合并
        if(!CollectionUtils.isEmpty(noLoginCartList)){
            //2.3遍历未登录购物车列表,判断当前登录购物车hash中是否包含当前商品skuId
            for (CartInfo noLoginCartInfo : noLoginCartList) {
                String hashKey = noLoginCartInfo.getSkuId().toString();
                if(loginHashOps.hasKey(hashKey)){
                    //包含该商品
                    CartInfo loginCartInfo = loginHashOps.get(hashKey);
                    //跟新数量
                    loginCartInfo.setSkuNum(loginCartInfo.getSkuNum() + noLoginCartInfo.getSkuNum());
                    loginCartInfo.setUpdateTime(new Date());
                    //更新选中状态
                    loginHashOps.put(hashKey, loginCartInfo);
                }else{

                    //2.4当前登录购物车hash中不包含该商品skuId,修改未登录购物车商品中用户id
                    noLoginCartInfo.setUserId(userId);
                    loginHashOps.put(hashKey, noLoginCartInfo);
                }
            }
        }

        //3.合并后将未登录购物车列表中的数据删除
        String noLoginRedisKKey = RedisConst.USER_KEY_PREFIX + userTempId + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.delete(noLoginRedisKKey);

        //4.查询已登录购物车商品列表
        List<CartInfo> loginCatrList = loginHashOps.values();
        if(!CollectionUtils.isEmpty(loginCatrList)){
            List<CartInfo> cartInfoList = loginCatrList.stream().sorted(((o1, o2) -> {
                return DateUtil.truncatedCompareTo(o1.getCreateTime(), o2.getCreateTime(), Calendar.SECOND);
            })).collect(Collectors.toList());
            return cartInfoList;
        }
        return null;
    }

    /**
     * 修改购物车商品选中状态
     * @param userId
     * @param skuId
     * @param isChecked
     */
    @Override
    public void updateCheck(String userId, Long skuId, Integer isChecked) {
        String redisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(redisKey);
        if(hashOps.hasKey(skuId.toString())){
            CartInfo cartInfo = hashOps.get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
            hashOps.put(skuId.toString(), cartInfo);
        }
    }

    /**
     * 删除购物车中指定商品
     * @param userId
     * @param skuId
     */
    @Override
    public void deleteCart(String userId, Long skuId) {
        String redisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(redisKey);
        hashOps.delete(skuId.toString());
    }

    /**
     * 根据指定用户查询购物车列表
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //1.构建用户购物车的hash结构key
        String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();

        //2.查询购物车列表,对购物车进行过滤
        if(!CollectionUtils.isEmpty(cartInfoList)){
            cartInfoList = cartInfoList.stream().filter(cartInfo -> {
                //true:需要数据,false:不需要数据
                return cartInfo.getIsChecked().intValue() == 1;
            }).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(cartInfoList)){
            throw new RuntimeException("没有需要结算的商品");
        }
        return cartInfoList;
    }
}